package com.zis.security.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zis.security.client.UserClient;
import com.zis.security.jwt.Audience;
import com.zis.security.jwt.JwtHelper;
import com.zis.security.model.AccessToken;
import com.zis.security.service.IAuthService;
import com.zis.starter.core.ResponseEntity;
import com.zis.starter.redis.RedisUtil;
import com.zis.system.model.GroupRes;
import com.zis.system.model.RoleRes;
import com.zis.system.model.User;
import com.zis.system.model.UserRole;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Create by wangshen 2018/4/23
 */
@Service
public class AuthServiceImpl implements IAuthService {

    @Autowired
    private Audience audience;

    @Autowired
    private UserClient userClient;

    @Autowired
    private RedisUtil redisUtil;


    /**
     * 根据token为用户进行鉴权
     * @param token
     * @return
     * @throws Exception
     */
    @Override
    public ResponseEntity userAuthentication(String token) throws Exception {
        if (token == null || token.equals("")) {
            return ResponseEntity.failure("token信息错误，鉴权失败");
        }
        // 获取完整的token信息
        if(!redisUtil.exists("system:login:"+token)){
            return ResponseEntity.failure("token不存在或已失效，请重新登陆");
        }
        AccessToken accessToken = (AccessToken) redisUtil.get("system:login:"+token);
        if (accessToken == null) {
            return ResponseEntity.failure("token不存在或已失效，请重新登陆");
        }
        token = accessToken.getToken_prefix()+"."+accessToken.getToken()+"."+accessToken.getToken_suffix();
        // 根据token获取用户信息
        Claims claims = JwtHelper.parseJWT(token, audience.getBase64Secret());
        if (claims == null) {
            return ResponseEntity.failure("token不存在或已失效，请重新登陆");
        }

        JSONObject resultMap = new JSONObject();
        //===============进行用户鉴权处理===============
        // 获取用户信息
        String userId = String.valueOf(claims.get("userId"));
        String groupId = null;
        ResponseEntity userEntity = userClient.selectById(userId);
        if (userEntity.getCode() == 0) {
            User user = JSONObject.parseObject(JSON.toJSONString(userEntity.getRespData()), User.class);
            groupId = user.getGroupId();
            resultMap.put("userId", user.getUserId());
            resultMap.put("userName", user.getRealName());
            resultMap.put("userType", user.getUserType());
            resultMap.put("code", accessToken.getAuthCode());
            resultMap.put("avator", "https://file.iviewui.com/dist/a0e88e83800f138b94d2414621bd9704.png");
        }
        // 获取用户角色信息
        ResponseEntity userRoleEntity = userClient.findByUserId(userId);
        List<UserRole> userRoleList = new ArrayList<>();
        if (userRoleEntity.getCode() == 0) {
            userRoleList = JSONObject.parseArray(JSON.toJSONString(userRoleEntity.getRespData()), UserRole.class);
        }
        // 获取角色的资源信息
        List<RoleRes> userResList = new ArrayList<>();
        for (UserRole userRole : userRoleList) {
            List<RoleRes> roleResList = userClient.findByRoleId(userRole.getRoleId());
            if (roleResList != null && roleResList.size() > 0) {
                userResList.addAll(roleResList);
            }
        }
        // 获取用户组资源信息
        List<GroupRes> groupResList = new ArrayList<>();
        if (groupId != null && !groupId.equals("")) {
            groupResList = userClient.findByGroupId(groupId);
        }
        //将角色资源封装到Map
        Map<String, String> userResMap = new HashMap<>();
        for (RoleRes roleRes : userResList) {
            userResMap.put(roleRes.getRemarks(), roleRes.getRemarks());
        }
        for (GroupRes groupRes : groupResList) {
            userResMap.put(groupRes.getRemarks(), groupRes.getRemarks());
        }
        resultMap.put("resMap", userResMap);
        resultMap.put("token", token);
        //权限列表写入redis中
        redisUtil.set("system:auth:"+token, userResMap, accessToken.getExpires_in());
        return ResponseEntity.success(JSON.parseObject(JSON.toJSONString(resultMap)));
    }

    /**
     * 验证用户功能权限
     * @param params 包含token与校验的标识
     * @return
     * @throws Exception
     */
    @Override
    public ResponseEntity userAuthVerify(JSONObject params) throws Exception {
        if(params == null){
            return ResponseEntity.failure("没有需要校验的信息");
        }
        if(!params.containsKey("token")||params.getString("token").equals("")){
            return ResponseEntity.failure("校验所需token不存在");
        }
        if(!params.containsKey("identify")||params.getString("identify").equals("")){
            return ResponseEntity.failure("没有需要校验的标识");
        }
        String token = params.getString("token");
        AccessToken accessToken = (AccessToken) redisUtil.get("system:login:"+token);
        String jsonWebToken = accessToken.getToken_prefix()+"."+token+"."+accessToken.getToken_suffix();
        if(!redisUtil.exists("system:auth:"+jsonWebToken)){
            return ResponseEntity.failure("token信息已过期");
        }
        Map<String, String> resMap = (Map<String, String>) redisUtil.get("system:auth:"+jsonWebToken);
        if(resMap.containsKey(params.getString("identify"))){
            return ResponseEntity.success("200");
        }
        return ResponseEntity.failure("403");
    }

    /**
     * 校验token的合法性
     * @param token
     * @return
     * @throws Exception
     */
    @Override
    public ResponseEntity tokenVerify(String token) throws Exception {
        if(token==null||token.equals("")){
            return ResponseEntity.failure("校验所需token不存在");
        }
        if(!redisUtil.exists("system:login:"+token)){
            return ResponseEntity.failure("token无效或已过期");
        }
        AccessToken accessToken = (AccessToken) redisUtil.get("system:login:"+token);
        String jsonWebToken = accessToken.getToken_prefix()+"."+token+"."+accessToken.getToken_suffix();
        Claims claims = JwtHelper.parseJWT(jsonWebToken, audience.getBase64Secret());
        if (claims == null) {
            return ResponseEntity.failure("不合法的token");
        }
        // token合法将用户的auth_code返回给api-gateway
        JSONObject jsonObj = new JSONObject();
        jsonObj.put("authCode", accessToken.getAuthCode());
        jsonObj.put("userId", claims.get("userId"));
        return ResponseEntity.success(jsonObj);
    }
}
